Java基础

Java 基础

异常类

异常说明

如果出错,创建出一个异常类对象,抛出相关信息

继承关系

1
2
3
4
5
6
7
8
9
10
        Throwable
| - Error java内部错误 不会捕获异常 (内部错误)
| - Exception | - RuntimeExecption 运行异常 运行阶段 nullpoint
| - CheckedException 检查异常 编译阶段 (外部错误) 文件 url IOException等

RuntimeExecption :
空指针 *ptr = null
数组越界 a[10] -> a[111]
算数异常 int 1/0
类型转换异常 shrot s1 = s1 + 1

Throw & Throws

  • 位置不同

    throw 是跟着异常对象 用在函数内

    throws 跟着异常类 用在函数上

    1
    2
    throw new NumberFormateException();
    int div(int a, int b ) throws Exception{}
  • 功能性

    告知

    • throws 告知可能会抛出异常
    • throw 某部分执行到throw一定抛出具体异常对象 且功能结束,告知异常

    消极处理

    • 真正处理的是 函数的上级调用者 即:抛出 而不是用try catch 捕获

Finally

try中执行到return语句,不会直接return, 先计算return表达式,把结果保存到临时栈,再执行finally语句,之后才把临时栈的结果返回。

Java容器

容器模型

1566981010621

1
2


20991168562147317681_wps图片

###

装箱&拆箱

int 与 integer区别: 数据类型与包装类区别

int:直接存数值 (初始化 = 0)

integer:引用指向这个对象(初始值 null)

integer a =1; -> integer a = integer.valueOf(1);

JavaI/O流

字符流

String 、StringBuild、 StringBuffer区别

  • String 定义字符的数据变量
  • StringBuild StringBuffer 都是拼接字符串,
  • ”a“+”b“ string用到两个字符串变量 ,实际上只用一个把两个拼接,另一个释放就好。
  • StringBuffer 采用同步机制 但效率慢 。。同理StringBuild

Java并发

线程内存模型

20170328111450634

特点:

  1. 每个线程需要从主内存获取 变量的值
  2. 获取数据之后回放入自己的工作内存中,都是主内存拷贝的副本
  3. 线程间无法直接访问对方工作内存

线程工作状态

20170328142908765

  1. lock(锁定):在某一个线程在读取主内存的时候需要把变量锁定。
  2. unlock(解锁):某一个线程读取玩变量值之后会释放锁定,别的线程就可以进入操作 。
  3. read(读取):从主内存中读取变量的值并放入工作内存中 。
  4. load(加载):从read操作得到的值放入工作内存变量副本中 。
  5. use(使用):把工作内存中的一个变量值传递给执行引擎 。
  6. assign(赋值):它把一个从执行引擎接收到的值赋值给工作内存的变量 。
  7. store(存储):把工作内存中的一个变量的值传送到主内存中 。
  8. write(写入):把store操作从工作内存中一个变量的值传送到主内存的变量中。

线程内部方法

806956-20180120151328678-189155379

单线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class one extends Thread{
public void run(){........};
}
///////////////////2////////////
public class two implements Runnable{
public void run(){......};
}
/////////////3//////////内部////////
new Thread(new Runnable(){
public void run(){ sout("sdfs") ; }
});
new Thread(()->{
sout("sdfs") ;
});
///////////
one a = new one();
two b = new two();
a.start(), b.start();

####

多线程

使用线程池

利用线程池管理线程的创建销毁,【缓存功能】

  1. 降低资源消耗
  2. 提高响应速度
  3. 线程可管理
常用线程池
  1. CacheThreadPool 无界 SynchronizedQueue 无缓存队列 接收任务直接处理
  2. FixedThreadPool 有界 LinkedBlokingQueue 列表阻塞队列 无界队列可缓存 读写分离
  3. SingleThreadPool 单一 LinkedBlokingQueue 指定队列 1
  4. ScheduledThreadPoll 定时周期
  • CachedThreadPool 无界线程池

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public class CachedThreadPoolTest{
    psvm{
    ExecutorService exec = Executors.newCachedThreadPool();
    for(20 times)
    {
    exec.execute(new WorkTask());
    }
    exec.shutdown();
    }
    }
    //构造方法 参数 (线程数 最大线程数 时间片 单位时间 阻塞队列)
    public static ExecutorService newCachedThreadPool(){
    return new ThreadpoolExecutor(0,Integer.MAX_VALUE,60L,TimeUnit.SECONDS,new Sysnchronous<Runnable>());
    }
  • FixedThreadPool 有界线程池

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public class FixedThreadPoolTest{
    psvm{
    ExecutorService exec = Executors.newFixedThreadPool(3);
    for(20 times)
    {
    exec.execute(new WorkTask());
    }
    exec.shutdown();
    }
    }
    public static ExecutorService newFixedThreadPool(int nThreads){
    return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());

    }
  • SingleThreadExecutor 单一线程池

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class SingleThreadPoolTest{
    psvm{
    ExecutorService exec = Executors.newSingleTheadExecutor();
    for(20 times)
    {
    exec.execute(new WorkTask());
    }
    exec.shutdown();
    }
    }
    public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
    (new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()));
  • ScheduledThreadPool 定时周期

    1
    2
    3
    4
    5
    6
    7
    public class ScheduledThreadPool{
    psvm{
    ExectorService exec = new Exector.newScheduledThreadExecutor(3);
    exec.execute(new WorkTask());
    exec.shutdown();
    }
    }
线程生命周期
  1. 新建 new创建线程 -> JVM分配内存 & 初始化成员变量的值
  2. 就绪 线程对象调用start() 创建方法调用栈 & 程序计数器 等待调度运行。
  3. 运行 处于就绪状态线程获得CPU,开始执行run()方法的线程执行体。
  4. 阻塞
    • 等待阻塞 run线程 执行 o.wait() jvm 会把线程放进等待队列
    • 同步阻塞 run线程 想获取对象的同步锁,该锁被别的线程占用,jvm把线程放入锁池中(lock pool)
    • 其他阻塞 Thread.sleep || t.join() || 发出IO请求
  5. 死亡
    • 正常结束 run() || call() 方法执行完成
    • 异常结束 线程抛出异常
    • 调用stop stop()

sdsdfsd

乐观锁 & 悲观锁

容器并发

CopyOnWrite容器

当我们向容器中添加元素,先copy该容器,把数据添加到copy容器中,再将数组引用指向容器。

实现线程安全:

  1. volatile修饰数组引用:确保数组内存可见性。【内存可见】-》 copy数组引用。
  2. 对容器修改操作同步。同一时刻只有一条线程修改容器
  3. 修改容器复制容器:修改操作都在新数组上,原数组可以放心读。
优点
  1. 并发读,实现读写分离 (当前容器不会添加任何元素) 无需加锁
缺点
  1. 内存占用,使用两个容器
  2. 只能保证数据最终一致性,无法保证实时性
使用场景

读多写少,且不要求实时性

ConcurrentHashMap

线程安全的HashTable改进版(一个线程访问,其他统统阻塞),而ConcurrentHashMap实现分段锁机制。

分段锁原理

ConcurrentHashMap由多个Segment构成,每个Segment都包含一张哈希表。每次操作只将操作数据所属的Segment锁起来,从而避免将整个锁住。

20170206102155332

1566979637383

每个Segment守护一个HashEntry数组的元素,当对hashEntry数组数据修改是,必须先获取对应的Segment锁(就是分段锁机制)

ConcurrentHashMap内部包含了Segment数组,而每个Segment又继承自ReentrantLock,因此它是一把可重入的锁。

锁机制

  1. 脏读:a事务 读到 b事务 未提交的数据

    ​ 解决

    • 修改->排它锁,事务提交才释放,读取 ->共享锁
    • 共享锁 (很多人可以读) 【有人想修改】 -》 排它锁 ,修改完毕后,其他人重新读数据时发现已经不同 ,(他运行事务未提交就释放共享锁) 导致不能避免 不可重复读
  2. 幻读: 同一事务,同样的操作读取两次,发现多了几条或者少了几条。 新增 删除的打扰

    ​ 说明:

    • a事务 修改全表数据行, b事务插入一条新数据 a事务发现还有一条没有修改 ,就像发生幻觉一样。

    • 事务T1:查询表中所有记录

      -->事务T2:插入一条记录
      -->事务T2:调用commit进行提交

      事务T1:再次查询表中所有记录

      此时事务T1两次查询到的记录是不一样的,称为幻读。

    ​ 解决:

    • 采用范围锁,锁定检索范围只读。
  3. 不可重复读: 统一事务读取两次,发现内容不同

    ​ 原因:执行select不加读锁(别人就改了)

    ​ 解决:

    • 推迟事务2执行,知道事务1提交或回退。
    • 在事务提交时检查事务的顺序性,可以让事务2先提交,事务1后提交时,如果顺序是(1->2)则事务1会回退重读 (2 -> 1) 那没事了
    • 读取数据加 共享锁 修改数据加排它锁 都是 事务提交才释放锁
  4. 丢失修改

    • a事务读取数据,更新数据 b事务读取数据 更新数据 ,a先提交 ,b后提交 ,a的修改操作丢失了 解决+ 排它锁
  5. 事务隔离五种级别:

    • TRANSACTION_NONE 不使用事务。
    • TRANSACTION_READ_UNCOMMITTED 允许脏读。
    • TRANSACTION_READ_COMMITTED 防止脏读,最常用的隔离级别,并且是大多数数据库的默认隔离级别。
    • TRANSACTION_REPEATABLE_READ 可以防止脏读和不可重复读。
    • TRANSACTION_SERIALIZABLE 可以防止脏读,不可重复读取和幻读,(事务串行化)会降低数据库的效率。

乐观锁CAS & 悲观锁

  • 数据库

    • 悲观锁 for update 行级锁
    • 乐观锁 version字段 比较上次版本号 如果同 更新成功 ,不同,再(重复读)读 比较 写
  • jdk

    • 悲观锁 sync
    • 乐观锁 compose & Swap 原子类 内部使用CAS实现
  • 思想 业务场景&实现方式

    • 乐观锁 认为读多写少,遇到并发的可能性低,写数据线查看对应的版本号,自己加锁操作,之后比较版本号是否一致,之后写入。

CAP

  1. 高一致性c:分布式系统备份中,数据是否同一时刻都一直
  2. 高可用性a:集群节点故障,整体是否还能响应客户端请求
  3. 分区容忍性p:对通信时限的要求,

一致性算法

Paxos决议达成一致

想当learners的proposer去acceptor投简历

  1. 角色:Proposer、Acceptor、Learners
  2. 阶段:
    • 准leader确定 【proposer的N提案proposer请求,acceptor的v承诺】。
    • leader确定 【proposer的多数票选[N,V]acceptor请求 ,送给acceptor,则答应成为learners】。
ZAB原子消息广播协议

有王国的带纸和广播的人

三大步骤

  1. 崩溃恢复:leader服务器崩溃,ZAB进入恢复状态,选举新的leader
  2. 数据同步:新leader会与过半以上服务器数据同步,ZAB退出崩溃恢复模式,进入消息广播
  3. 消息广播:有新的服务器加入,会自动找到消息广播的leader,与它进行数据同步工作,进leader服务器数据发送到其他服务器。
Raft

###

Java网络通讯

NIO

NIO分为阻塞和分蛛丝啊量

数据库原理

垂直切分&水平切分

垂直切分:

  • :+1:表与表的io争夺
  • :no_entry:单表数据量增长压力

水平切分: 相反

1
2
3
4
5
6
7
8
产品表 订单表 用户表
10w steady 200w UP 100w UP
垂直切分:
[server] | 产品表 订单表 | 用户表[server]
水平切分:
| -男 -----link--- - 已完成订单 [server]
| 用户表 订单表 - 未完成订单 [server]
| -女 [server]

索引

索引种类
  • 普通索引 index[userName] on (username(length))

  • 唯一索引 unique [indexName] on (username(length)) 索引列唯一

  • 主键索引 primary key (id)

  • 组合索引 name, city, age建到一个索引里 alter table mytable add index name_city_age(name(10), city, age);

    相当于 mysql组合最左前缀

    1. username,city,age
    2. username,city :select * from mytable where username =”admin” city =”cc”
    3. username: select * from mytable where username=‘ss”
索建立时机

<,<=,=,>,>=,BETWEEN,IN,以及某些时候的LIKE才会使用索引

city & age 建立索引 ,mytable 的username也要建立

1
2
3
select t.Name
from mytable t left join mytable m
on t.Name = m.username where t.age = 20 and t.city = "ss"
索引不足
  • up 查询速度

  • down 表更新速度 :insert 、update delete 需要维护主表之外还要同步保存索引文件,在聚集索引层面上说就是需要维护这个平衡树,每次的更新都会破坏原有树的状态,需要重新梳理树的结构,如果数据量很大,更新表可能就开始变得困难

  • ​ 聚集索引 (主键索引)

  • img

  • ​ 非聚集索引 (单一索引 普通索引 组合索引)

    可以通过非聚集索引所提供的记录查到对应的聚集索引(主键) 然后再用主键查。

  • img

  • 无论有什么方式查表,都会利用主键以聚集索引的方式来定位数据,聚集索引(主键)是通往真实数据的唯一通道。

  • 索引占用磁盘索引文件

1
2
3
4
5
6
7
8
9
10
create table mytable(
ID int not null,
#index [indexName] (username(length))
username varchar(16) not null
city VARCHAR(50) NOT NULL,
age INT NOT NULL );
#index
create index indexName on mytable(username(length));
alter mytable add idnex [indexName] on (username(length))
drop index [indexName] on mytable

MyISAM&InnoDB引擎

区别

  1. 事务 InnoDB 支持 外键、事务、行级锁 。MyISAM(不支持)
  2. 读写性能MyISAM读性能up,写性能up(除了有索引update的InnoDB)
  3. 索引数据MyISAM索引和数据分开,索引压缩 -》非聚集索引 b+数检索算法检索,找到对应的数据域的值(是主键的地址) ;InnoDB索引和数据时紧密联系
  4. delete table mytabl InnoDB不会重新建立表, 是一行一行删
  5. 锁表 锁行InnoDB可能锁全表(而不是行级锁)当 like%aaa% 扫不确定范围 ; 和 where 条件没有主键时。

使用

  1. 执行大量的INSERT或UPDATE操作需要事务 : InnoDB
  2. 大量的SELECT查询读多写少的项目,可以考虑使用MyISAM

三范式

  1. 原子性

    1567134589943

  2. 2NF

    一张表里描述了两个事情:学生信息、课程信息

    姓名、年龄 -> 学号 学分 -> 课程

    1567134647795

    1567134679588

  3. 3NF

    某个字段必须是主键

    学院地址、学校电话 -> 学院 学院 -》学号

    1567134819520

1567134873704

其他

== equal hashcode区别

  • == equal 都是判断引用地址是否相同
  • string equal 就是 1.判断是否为string类型 2.遍历每个char字符
  • 重写equal可以判断内容是否相同
  • hashcode 更多应用在set 无重复数字,(每增加一个 就要和n-1个数字equal的缺点)。
  • 每个数都有对应的 hashcode 映射到哈希表中,(每个数有对应的坑和他的坑号码)
  • 比较只要看他手上的坑号码是否相同,不同就不等,同就equal判断内容。

接口和抽象类

  • 抽象类通过继承来使用

  • 接口通过实现类使用

  • 抽象类可以提供抽象方法和实现方法

  • 接口类实现方法需要用default定义 lamdba表达式

强制类型转换错误

1
2
short s1 = 1; 把 整数1 转换为 short类型
s1 = 1 + s1 ; error 右边会 1+ s1转为int类型 强制转换成s1 short发生错误

length方法

  • 数组长度 .length 属性
  • String获取长度 length()方法
  • 集合获取长度 size()方法
  • 文件获取长度 length()方法

介绍数据库索引

1、索引的种类4,索引生效时刻,主键、组合,普通,聚集索引和非聚集索引

线程安全问题

线程安全需要你使多个线程安全有序的访问修改同一个资源,而不会造成冲突。(修改丢弃、脏读、不可重复读

0%